import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
import { promisify } from 'util';

// 使用promisify将fs的异步API转为Promise形式
const readdir = promisify(fs.readdir);
const stat = promisify(fs.stat);

export class PushFileToDevicePanel {
	/**
	 * Track the currently panel. Only allow a single panel to exist at a time.
	 */
	public static currentPanel: PushFileToDevicePanel | undefined;

	public static readonly viewType = 'pushFileToDevice';

	private readonly _panel: vscode.WebviewPanel;
	private readonly _extensionUri: vscode.Uri;
	private _disposables: vscode.Disposable[] = [];
	private static _isDevelopment: boolean = true;
	private _lastDirectoryPath: string = '';
	private _lastDevicePath: string = '';

	public static setDevelopmentMode(isDev: boolean) {
		PushFileToDevicePanel._isDevelopment = isDev;
	}

	public static isDevelopmentMode(): boolean {
		return PushFileToDevicePanel._isDevelopment;
	}

	public static createOrShow(extensionUri: vscode.Uri) {
		const column = vscode.window.activeTextEditor
			? vscode.window.activeTextEditor.viewColumn
			: undefined;

		// If we already have a panel, show it.
		if (PushFileToDevicePanel.currentPanel) {
			PushFileToDevicePanel.currentPanel._panel.reveal(column);
			return;
		}

		// Otherwise, create a new panel.
		const panel = vscode.window.createWebviewPanel(
			PushFileToDevicePanel.viewType,
			'Push File To Device',
			column || vscode.ViewColumn.One,
			getWebviewOptions(extensionUri),
		);

		PushFileToDevicePanel.currentPanel = new PushFileToDevicePanel(panel, extensionUri);
	}

	public static revive(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) {
		PushFileToDevicePanel.currentPanel = new PushFileToDevicePanel(panel, extensionUri);
	}

	private constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) {
		this._panel = panel;
		this._extensionUri = extensionUri;
		
		// 初始化为用户当前打开的项目目录
		this._lastDirectoryPath = this._getCurrentWorkspaceFolder();

		// Set the webview's initial html content
		this._update();

		// Listen for when the panel is disposed
		// This happens when the user closes the panel or when the panel is closed programmatically
		this._panel.onDidDispose(() => this.dispose(), null, this._disposables);

		// Update the content based on view changes
		this._panel.onDidChangeViewState(
			() => {
				if (this._panel.visible) {
					this._update();
				}
			},
			null,
			this._disposables
		);

		// Handle messages from the webview
		this._panel.webview.onDidReceiveMessage(
			async (message) => {
				switch (message.command) {
					case 'alert':
						vscode.window.showErrorMessage(message.text);
						return;
					case 'browseFile':
						this._browseFile();
						return;
					case 'getDevices':
						this._getConnectedDevices();
						return;
					case 'pushFile':
						this._pushFileToDevice(message.filePath, message.deviceId, message.targetPath);
						return;
					case 'getFiles':
						this._getFiles(message.path);
						return;
					case 'getDeviceFiles':
						this._getDeviceFiles(message.deviceId, message.path);
						return;
					case 'filesSelected':
						this._handleFilesSelected(message.files);
						return;
					case 'confirmTasks':
						this._handleConfirmTasks(message.devices, message.tasks);
						return;
				}
			},
			null,
			this._disposables
		);
	}

	private async _browseFile() {
		const fileUri = await vscode.window.showOpenDialog({
			canSelectMany: false,
			openLabel: 'Select File',
			canSelectFiles: true,
			canSelectFolders: false
		});

		if (fileUri && fileUri[0]) {
			this._panel.webview.postMessage({
				command: 'fileSelected',
				filePath: fileUri[0].fsPath
			});
		}
	}

	/**
	 * 获取连接的设备
	 */
	private async _getConnectedDevices() {
		// Use hdc list targets command to get real device information
		const { exec } = require('child_process');
		// 使用bash作为shell执行命令，但不使用交互式模式
		exec(`hdc list targets`, {
		}, (error: any, stdout: string, stderr: string) => {
			if (error) {
				console.error(`Error executing hdc command: ${error.message}`);
				this._panel.webview.postMessage({
					command: 'devicesDetected',
					devices: [],
					error: `Error executing hdc command: ${error.message}`
				});
				return;
			}

			if (stderr) {
				console.warn(`hdc command warning: ${stderr}`);
			}

			// Parse the output of hdc list targets
			const devices = this._parseHdcOutput(stdout);
			
			if (devices.length === 0) {
				console.log("No devices found, hdc output was:", stdout);
			}

			// Send devices to webview
			this._panel.webview.postMessage({
				command: 'devicesDetected',
				devices: devices
			});
		});
	}

	private _parseHdcOutput(output: string): Array<{id: string, name: string}> {
		const devices: Array<{id: string, name: string}> = [];
		const lines = output.trim().split('\n');
		
		for (let i = 0; i < lines.length; i++) {
			const line = lines[i].trim();
			if (line.includes('Empty')) {
				break;
			}

			if (line) {
				devices.push({ id: line, name: line });
			}
		}
		
		return devices;
	}

	private _pushFileToDevice(filePath: string, deviceId: string, targetPath: string) {
		// Mock implementation - replace with actual file push logic
		if (!filePath || !deviceId || !targetPath) {
			this._panel.webview.postMessage({
				command: 'transferError',
				message: 'Missing required parameters'
			});
			return;
		}

		// Start progress
		this._panel.webview.postMessage({
			command: 'transferStarted'
		});

		// Simulate progress updates
		let progress = 0;
		const interval = setInterval(() => {
			progress += 10;
			this._panel.webview.postMessage({
				command: 'transferProgress',
				progress: progress
			});

			if (progress >= 100) {
				clearInterval(interval);
				// Complete transfer
				this._panel.webview.postMessage({
					command: 'transferComplete',
					success: true
				});
			}
		}, 300);
	}

	public doRefactor() {
		// Send a message to the webview webview.
		// You can send any JSON serializable data.
		this._panel.webview.postMessage({ command: 'refactor' });
	}

	public dispose() {
		PushFileToDevicePanel.currentPanel = undefined;

		// Clean up our resources
		this._panel.dispose();

		while (this._disposables.length) {
			const x = this._disposables.pop();
			if (x) {
				x.dispose();
			}
		}
	}

	private _update() {
		const webview = this._panel.webview;

        this._panel.title = 'Push File To Device';
		this._panel.webview.html = this.getProductionHtml(webview);
	}

	private getProductionHtml(webview: vscode.Webview) {
		// Get the local path to main script run in the webview
		const scriptUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, 'webview-ui', 'dist', 'assets', 'index.js'));
		
		// Get the local path to css styles
		const styleUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, 'webview-ui', 'dist', 'assets', 'index.css'));
		
		// Use a nonce to only allow specific scripts to be run
		const nonce = getNonce();
		
		return `<!DOCTYPE html>
			<html lang="en" class="dark">
			<head>
				<meta charset="UTF-8">
				<meta name="viewport" content="width=device-width, initial-scale=1.0">
				<title>Push File To Device</title>
				<link href="${styleUri}" rel="stylesheet">
				<script nonce="${nonce}">
					// Set initial route for the Vue app
					window.initialRoute = '#/pushFileToDevice';
					// Setup VSCode API access
					const vscode = acquireVsCodeApi();
					window.vscode = vscode;
				</script>
			</head>
			<body>
				<div id="app"></div>
				<script type="module" nonce="${nonce}" src="${scriptUri}"></script>
			</body>
			</html>`;
	}

	private async _getDevicePath(dirPath: string) {
		try {
			// 确保路径存在且是一个目录
			let normalizedPath = dirPath;
			
			// 如果path为空，使用上次的目录路径
			if (!normalizedPath) {
				normalizedPath = this._lastDevicePath;
			}
			
			// 检查路径是否存在
			if (!fs.existsSync(normalizedPath)) {
				// 如果路径不存在，尝试使用用户的项目目录或主目录
				normalizedPath = this._getCurrentWorkspaceFolder();
			}

			// 获取目录内容
			const entries = await readdir(normalizedPath, { withFileTypes: true });
			
			// 处理文件和目录
			const files = entries.map(entry => {
				return {
					name: entry.name,
					isDirectory: entry.isDirectory()
				};
			});

			// 如果不是根目录，添加上级目录选项
			if (normalizedPath !== '/') {
				files.unshift({
					name: '..',
					isDirectory: true
				});
			}

			// 更新最后访问的目录路径
			this._lastDirectoryPath = normalizedPath;

			// 发送文件列表到前端
			this._panel.webview.postMessage({
				command: 'fileList',
				files: files,
				path: normalizedPath
			});

		} catch (error) {
			console.error('Error reading directory:', error);
			
			// 发送错误信息
			this._panel.webview.postMessage({
				command: 'fileList',
				files: [],
				path: dirPath || this._lastDirectoryPath,
				error: `Error reading directory: ${error instanceof Error ? error.message : String(error)}`
			});
		}
	}

	/**
	 * 获取本地文件列表
	 * @param dirPath 目录路径
	 */
	private async _getFiles(dirPath: string) {
		try {
			// 确保路径存在且是一个目录
			let normalizedPath = dirPath;
			
			// 如果path为空，使用上次的目录路径
			if (!normalizedPath) {
				normalizedPath = this._lastDirectoryPath;
			}
			
			// 检查路径是否存在
			if (!fs.existsSync(normalizedPath)) {
				// 如果路径不存在，尝试使用用户的项目目录或主目录
				normalizedPath = this._getCurrentWorkspaceFolder();
			}

			// 获取目录内容
			const entries = await readdir(normalizedPath, { withFileTypes: true });
			
			// 处理文件和目录
			const files = entries.map(entry => {
				return {
					name: entry.name,
					filePath: path.join(normalizedPath, entry.name),
					isDirectory: entry.isDirectory()
				};
			});

			// 如果不是根目录，添加上级目录选项
			if (normalizedPath !== '/') {
				files.unshift({
					name: '..',
					filePath: path.join(normalizedPath, '..'),
					isDirectory: true
				});
			}

			// 更新最后访问的目录路径
			this._lastDirectoryPath = normalizedPath;

			// 发送文件列表到前端
			this._panel.webview.postMessage({
				command: 'fileList',
				files: files,
				path: normalizedPath
			});

		} catch (error) {
			console.error('Error reading directory:', error);
			
			// 发送错误信息
			this._panel.webview.postMessage({
				command: 'fileList',
				files: [],
				path: dirPath || this._lastDirectoryPath,
				error: `Error reading directory: ${error instanceof Error ? error.message : String(error)}`
			});
		}
	}

	private _handleFilesSelected(files: Array<{name: string, path: string}>) {
		// 这里可以处理用户选择的文件
		console.log('Files selected:', files);
		
		// 如果需要，可以进一步处理选择的文件
		// 例如，将文件添加到某个列表，或者准备推送到设备
		
		// 可以通知前端选择已处理
		this._panel.webview.postMessage({
			command: 'filesProcessed',
			success: true
		});
	}

	private _getCurrentWorkspaceFolder(): string {
		const workspaceFolders = vscode.workspace.workspaceFolders;
		if (workspaceFolders && workspaceFolders.length > 0) {
			return workspaceFolders[0].uri.fsPath;
		}
		return require('os').homedir();
	}

	private async _getDeviceFiles(deviceId: string, dirPath: string) {
		if (!deviceId) {
			this._panel.webview.postMessage({
				command: 'deviceFileList',
				files: [],
				path: dirPath || this._lastDevicePath,
				error: 'No device selected'
			});
			return;
		}

		// 使用默认路径如果没有提供
		let path = dirPath;
		
		// 如果没有传入路径，则使用上次访问的设备路径
		if (!path || path.trim() === '') {
			// 如果上次访问的设备路径为空，则使用根目录
			path = this._lastDevicePath || '/';
			console.log(`Using cached device path: ${path}`);
		}
		
		// 使用hdc shell执行ls命令
		const { exec } = require('child_process');
		
		try {
			// 构建命令：hdc -t <deviceId> shell ls -la <path>
			const cmd = `hdc -t ${deviceId} shell "ls -la ${path}"`;
			console.log(`Executing command: ${cmd}`);
			
			exec(cmd, (error: any, stdout: string, stderr: string) => {
				if (error) {
					console.error(`Error executing hdc shell command: ${error.message}`);
					this._panel.webview.postMessage({
						command: 'deviceFileList',
						files: [],
						path: path,
						error: `Error executing command: ${error.message}`
					});
					return;
				}

				if (stderr) {
					console.warn(`hdc shell command warning: ${stderr}`);
				}

				// 解析ls命令的输出
				const files = this._parseLsOutput(stdout, path);
				
				// 保存最后访问的设备路径
				this._lastDevicePath = path;
				
				// 发送文件列表到前端
				this._panel.webview.postMessage({
					command: 'deviceFileList',
					files: files,
					path: path
				});
			});
		} catch (error) {
			console.error('Error executing hdc shell command:', error);
			this._panel.webview.postMessage({
				command: 'deviceFileList',
				files: [],
				path: path,
				error: `Error: ${error instanceof Error ? error.message : String(error)}`
			});
		}
	}

	private _parseLsOutput(output: string, currentPath: string): Array<{name: string, isDirectory: boolean}> {
		const files: Array<{name: string, isDirectory: boolean}> = [];
		const lines = output.trim().split('\n');
		
		// 如果不是根目录，添加上级目录
		if (currentPath !== '/' && currentPath !== '/sdcard') {
			files.push({
				name: '..',
				isDirectory: true
			});
		}
		
		// 跳过第一行，它通常是"total X"
		for (let i = 1; i < lines.length; i++) {
			const line = lines[i].trim();
			if (!line) continue;
			
			// 典型的ls -la输出格式：
			// drwxr-xr-x 2 root root 4096 Jan 1 12:34 dirname
			// -rw-r--r-- 1 root root 1234 Jan 1 12:34 filename
			const parts = line.split(/\s+/);
			if (parts.length < 7) continue; // 忽略格式不正确的行
			
			const permissions = parts[0];
			// 文件名是最后一个部分
			const name = parts.slice(7).join(' ');
			
			// 忽略当前目录和上级目录的条目
			if (name === '.' || name === '..') continue;
			
			// 判断是否是目录（权限字符串以'd'开头）
			const isDirectory = permissions.startsWith('d');
			
			files.push({
				name,
				isDirectory
			});
		}
		
		return files;
	}

	// TODO: 是否要执行hdc mount命令？
	private _handleConfirmTasks(devices: string[], tasks: Array<{id: string, fileName: string, devicePath: string, filePath: string}>) {
		// 这里可以处理用户确认的任务
		console.log('Devices selected:', devices);
		console.log('Tasks confirmed:', tasks);
		
		if (devices.length === 0 || tasks.length === 0) {
			this._panel.webview.postMessage({
				command: 'tasksProcessed',
				success: false,
				error: '无效的设备或任务'
			});
			return;
		}
		

		// 创建进度提示
		vscode.window.withProgress({
			location: vscode.ProgressLocation.Notification,
			title: `Begin to push file to device...`,
			cancellable: true
		}, async (progress, token) => {
			const total = tasks.length * devices.length;
			let completed = 0;
			const { exec } = require('child_process');
			
			try {
				// 为每个设备执行任务
				for (const deviceId of devices) {
					if (token.isCancellationRequested) {
						break;
					}
					
					// 处理每个文件任务
					for (const task of tasks) {
						if (token.isCancellationRequested) {
							break;
						}
						
						// 更新进度
						completed++;
						progress.report({
							message: `推送 ${task.fileName} 到 ${deviceId} (${completed}/${total})`,
							increment: (100 / total)
						});
						
						try {
							// 构建hdc命令
							const cmd = `hdc -t ${deviceId} file send "${task.filePath}" "${task.devicePath}/${task.fileName}"`;
							console.log(`Executing: ${cmd}`);
							
							// 同步执行命令
							const stdout = exec(cmd, { encoding: 'utf8' }, (error: any, stdout: string, stderr: string) => {
								if (error) {
									vscode.window.showErrorMessage(`Error pushing ${task.fileName} to ${deviceId}: ${error}`);
								}
								if (stdout.includes('Fail')) {
									vscode.window.showErrorMessage(`Error pushing ${task.fileName} to ${deviceId}: ${stdout}`);
								} else {
									console.log(`Successfully pushed ${task.fileName} to ${deviceId}:${task.devicePath}`);
									console.log(`Command output: ${stdout}`);
								}
							});
						
						} catch (error) {
							vscode.window.showErrorMessage(`Error pushing ${task.fileName} to ${deviceId}: ${error}`);
							// 继续处理下一个任务，不中断整个过程
						}
					}
				}
				
				// 所有任务完成后通知前端
				this._panel.webview.postMessage({
					command: 'tasksProcessed',
					success: true,
					message: `成功推送文件到设备`
				});
				
				return true; // 返回一个已解决的Promise以完成进度显示
			} catch (error) {
				vscode.window.showErrorMessage(`Error during file transfer: ${error instanceof Error ? error.message : String(error)}`);
				this._panel.webview.postMessage({
					command: 'tasksProcessed',
					success: false,
					error: `文件传输过程中发生错误: ${error instanceof Error ? error.message : String(error)}`
				});
				
				return false; // 返回一个已解决的Promise以完成进度显示
			}
		}).then(completed => {
			if (completed) {
				// Show success message with a button after progress is complete
				vscode.window.showInformationMessage(
					`Restart Device`,
					'Restart','Ignore'
				).then(selection => {
					// Handle button click
					if (selection === 'Restart') {
						vscode.window.showInformationMessage(`Begin Restart Device...`);
					}
				});
			}
		});
	}
}

function getWebviewOptions(extensionUri: vscode.Uri): vscode.WebviewOptions {
	return {
		// Enable javascript in the webview
		enableScripts: true,

		// And restrict the webview to only loading content from our extension's 'media' directory.
		localResourceRoots: [
			vscode.Uri.joinPath(extensionUri, 'media'),
			vscode.Uri.joinPath(extensionUri, 'webview-ui', 'dist')
		]
	};
}

function getNonce() {
	let text = '';
	const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
	for (let i = 0; i < 32; i++) {
		text += possible.charAt(Math.floor(Math.random() * possible.length));
	}
	return text;
}